#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <cassert>
#include <fstream>
#include "../comm/util.hpp"
#include "../comm/log.hpp"
#include "./include/mysql.h"

namespace ns_model
{
    using namespace ns_util;
    using namespace ns_log;

    struct Question
    {
        std::string number;    //题目的编号
        std::string title;     //题目的名称
        std::string star;      //题目的难度
        int cpu_limit;         //题目所用CPU的时间限制
        int mem_limit;         //题目所用内存的时间限制
        std::string desc;      //题目的描述
        std::string header;    //题目的预设代码
        std::string test;      //题目的测试用例
    };

    const std::string oj_question = "oj_questions";
    
    class model
    {
    private:
        std::unordered_map<std::string, Question> Questions;
    public:
        model()
        {}
#define NUM 64
        bool QueryMysql(const std::string& sql, std::vector<Question>* out)
        {
            //创建MySQL句柄
            MYSQL* my = mysql_init(nullptr);
            //设置编码格式
            mysql_set_character_set(my, "utf8");
            if(mysql_real_connect(my, "127.0.0.1", "LOJ", "lioujie66666..", "oj", 8080, nullptr, 0) == nullptr)
            {
                LOG(FATAL) << "mysql 连接建立失败" << std::endl;
                return false;
            }
            LOG(INFO) << "连接mysql成功" << std::endl;
            if(mysql_query(my, sql.c_str()) != 0)
            {
                LOG(WARNING) << "执行sql 语句失败 " << std::endl;
                return false;
            }
            //保存查询结果
            MYSQL_RES* ret = mysql_store_result(my);
            int rows = mysql_num_rows(ret);
            int cols = mysql_num_fields(ret);
            for(int i = 0;i < rows;++i)
            {
                MYSQL_ROW line = mysql_fetch_row(ret);
                Question q;
                q.number = line[0];
                q.title = line[1];
                q.star = line[2];
                q.desc = line[3];
                q.header = line[4];
                q.test = line[5];
                q.cpu_limit = atoi(line[6]);
                q.mem_limit = atoi(line[7]);

                out->push_back(q);
            }
            free(ret);
            //关闭MySQL连接
            mysql_close(my);

            return true;
        }

        bool GetAllQuestions(std::vector<Question>* out)
        {
            std::string sql = "select * from ";
            sql += oj_question;

            return QueryMysql(sql, out);
        }

        bool GetOneQuestion(const std::string& num, Question* out)
        {
            std::string sql = "select * from ";
            sql += oj_question;
            sql += " where number=";
            sql += num;
            std::vector<Question> result;
            if(QueryMysql(sql, &result))
            {
                if(result.size() == 1)
                {
                    *out = result[0];
                    return true;
                }
            }

            return false;
        }

        ~model()
        {}
    };
}
